package com.gdcp.config;

import com.gdcp.config.security.CustomUserService;
import com.gdcp.config.security.MyAccessDeniedHandler;
import com.gdcp.config.security.MyAuthenticationFailureHandler;
import com.gdcp.config.security.validate.ValidateCodeFilter;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder;
import org.springframework.security.config.annotation.method.configuration.EnableGlobalMethodSecurity;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.builders.WebSecurity;
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
import org.springframework.security.core.userdetails.UserDetailsService;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter;
import org.springframework.security.web.firewall.DefaultHttpFirewall;
import org.springframework.security.web.firewall.HttpFirewall;
import org.springframework.security.web.firewall.StrictHttpFirewall;

/**
 * @author 杨华京
 * @version 1.0
 * @description
 * @since 1.8
 * 参考博文：https://blog.csdn.net/wangxueqing52/article/details/82628407
 */
@Configuration
@EnableWebSecurity  //开启 Spring Security 权限控制和认证功能。
@EnableGlobalMethodSecurity(prePostEnabled = true)  //  启用方法级别的权限认证
public class SecurityConfig extends WebSecurityConfigurerAdapter {

    @Autowired
    private MyAccessDeniedHandler myAccessDeniedHandler;
    @Autowired
    private MyAuthenticationFailureHandler myAuthenticationFailureHandler;

    //注册UserDetailsService 的bean
    @Bean
    UserDetailsService customUserService(){
        return new CustomUserService();
    }

    @Override
    protected void configure(AuthenticationManagerBuilder auth) throws Exception {
        auth.userDetailsService(customUserService()).passwordEncoder(passwordEncoder());
    }

    @Bean
    public PasswordEncoder passwordEncoder() {
        // return PasswordEncoderFactories.createDelegatingPasswordEncoder();
        return new BCryptPasswordEncoder();
    }

    @Override
    protected void configure(HttpSecurity http) throws Exception {

        ValidateCodeFilter validateCodeFilter=new ValidateCodeFilter();
        validateCodeFilter.setAuthenticationFailureHandler(myAuthenticationFailureHandler);

        http.addFilterBefore(validateCodeFilter, UsernamePasswordAuthenticationFilter.class)
                .authorizeRequests()
                //.antMatchers("/render/comment/**").hasRole("ADMIN")
                .antMatchers("/","/render/product/**","/render/shop/queryShopByShopId",
                        "/render/news/queryNewsByNewsId","/render/user/register",
                        "/render/register").permitAll()
                .antMatchers( "/render/validate/CodeImage").permitAll()
                .anyRequest().authenticated() //任何请求,登录后可以访问
                .and()
                .formLogin()
                //这个表示登录页的地址，例如当你访问一个需要登录后才能访问的资源时，系统就会自动给你通过重定向跳转到这个页面上来。
                .loginPage("/render/login")
                //这个表示配置处理登录请求的接口地址，例如你是表单登录，那么 form 表单中 action 的值就是这里填的值。
                .loginProcessingUrl("/render/user/login")
                .successForwardUrl("/render/user/login02")
                .failureForwardUrl("/render/user/login02").permitAll() //登录页面用户任意访问
                .and()
                .logout().permitAll() //注销行为任意访问
                .and()
                .csrf().disable()
                .exceptionHandling()        //配置自定义403响应
                .accessDeniedHandler(myAccessDeniedHandler);
    }

    @Bean
    public HttpFirewall allowUrlEncodedSlashHttpFirewall() {
        return new DefaultHttpFirewall();
    }

    @Override
    public void configure(WebSecurity webSecurity) {
        webSecurity.httpFirewall(allowUrlEncodedSlashHttpFirewall());
        webSecurity.ignoring().antMatchers("/**/*.css","/**/*.js","/**/*.jpg","/**/*.gif","/**/*.png","/render/fonts/**");//放开所有静态资源
    }
}



















/*auth.userDetailsService(customUserService()).passwordEncoder(new PasswordEncoder(){

            @Override
            public String encode(CharSequence rawPassword) {
                return MD5Util.encode((String)rawPassword);
            }

            @Override
            public boolean matches(CharSequence rawPassword, String encodedPassword) {
                return encodedPassword.equals(MD5Util.encode((String)rawPassword));
            }}); //user Details Service验证*/
//auth.userDetailsService(customUserService());